#!/usr/bin/env python
"""Base object for all command operations in RyCE.  Any classes that are
inherited from this must meet this one requirement.  The filename and the class
name but be spelled exactly the same!
"""
#-IMPORTS-----------------------------------------------------------------------
import os
import logging
import plogging
import commands
#-CONSTANTS---------------------------------------------------------------------
IP = 'ip'
ARGS = 'args'
DOUBLE_LINE = '|========================================'
SINGLE_LINE = '|----------------------------------------'
CMD_PARAMS = {IP:'', ARGS:[]}
__plugin_name__ = 'cmdobj'
#-CLASSES-----------------------------------------------------------------------
class CmdObject(object):
    """This is an individual command object.  It is created by cmdfactory.py
    and passed around by cmdmgr.py.
    """
    def __init__(self,
                 p_id   = 0,
                 p_os   = 'posix',
                 p_env  = '',
                 p_cmd  = '',
                 p_path = '',
                 p_work = '',
                 p_args = None,
                 p_name = __plugin_name__):
        self.id = p_id      #-Id for the command in the queue.
        self.os = p_os      #-The OS this command should run on.
        self.env = p_env     #-A string to export into the environment.
        self.cmd = p_cmd     #-A command like python.exe, ls, ssh, etc...
        self.path = p_path    #-Path to the command should be run.
        self.wpath = p_work    #-Path in which to execute the command.
        self.args = p_args    #-Argument list for the command.
        self.name = p_name    #-Name of the subclassed command.
        self.proc = None      #-A pointer to the process
        self.retcode = -1
        self.rettxt = ''
        self.errtxt = ''
        self.timeout = 0
        self.timedout = False
        self._log = None
        self.s_cmd = self.__create_cmd__()

    def __create_cmd__(self):
        """Creates a string of the complete command-line command.  This can be
        run on the OS command-line.
        """
        t_cmd = ''
        if self.env != '':
            if self.os == 'posix':
                t_cmd = 'export %s; ' % self.env
            elif self.os == 'nt' or self.os == 'dos':
                t_cmd = 'set %s; ' % self.env
        if self.path != '':
            t_cmd += '%s%s' % (self.path, os.sep)
        t_cmd += self.cmd
        for arg in self.args:
            t_cmd += ' %s' % arg
        return t_cmd

    def __pre_execute(self):
        """Code that is executed before the command is run.
        """
        self._log.info(DOUBLE_LINE)
        self._log.info('| cmd=%s' % self.s_cmd)
        self._log.info('| cmd_id=%d; Executing the command.' % self.id)

    def __post_execute(self):
        """Code that is executed after the command is run.
        """
        if not self.timedout:
            self._log.info('| cmd_id=%d; Received the command back.' % self.id)
            self._log.info(SINGLE_LINE)
            self._log.info('| Return code: %s' % self.retcode)
            self._log.info(SINGLE_LINE)
            self._log.info('| Output:')
            self.rettxt.replace('\r', '')
            outtxt = self.rettxt.split('\n')
            for line in outtxt:
                self._log.info('| %s' % line)
        else:
            self._log.error('| cmd_id=%d; Timed-out!' % self.id)
        self._log.info(SINGLE_LINE)
        self._log.info('| cmd_id=%d; Complete.'% self.id)
        self._log.info(DOUBLE_LINE)

    def _execute(self):
        """Executes the command.
        """
        self.__pre_execute()
        (self.retcode, self.rettxt) = commands.getstatusoutput(self.s_cmd)
        self.__post_execute()

    def _start_log(self):
        """Creates a logger and attaches it to a file and stdout.
        """
        self._log = logging.getLogger(__name__)
        fileHndl = logging.FileHandler(plogging._make_log_filename(plogging.CMD_TYPE,
                                                                   self.id,
                                                                   self.name))
        fileHndl.setLevel(logging.DEBUG)
        formatter = logging.Formatter(plogging.DEFAULT_FORMAT)
        fileHndl.setFormatter(formatter)
        self._log.addHandler(fileHndl)
